package com.shangxian.giveithome.controller;

import com.shangxian.giveithome.code.AuthCode;
import com.shangxian.giveithome.code.CommonCode;
import com.shangxian.giveithome.code.FeiCode;
import com.shangxian.giveithome.code.UserCode;
import com.shangxian.giveithome.entity.*;
import com.shangxian.giveithome.exception.ExceptionUtils;
import com.shangxian.giveithome.mapper.NewReportMapper;
import com.shangxian.giveithome.result.Result;
import com.shangxian.giveithome.service.ApiService;
import com.shangxian.giveithome.utils.Base64Utils;
import com.shangxian.giveithome.utils.IdWorker;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

import static com.shangxian.giveithome.utils.DateTime.getDays;

@Api(tags = "授权模块")
@RequestMapping("/auth")
@RestController
public class AuthController {
    @Autowired
    private ApiService apiService;

    @Autowired
    private UserFeiController userFeiController;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private PasswordEncoder passwordEncode;

    @Resource
    private NewReportMapper newReportMapper;

    @ApiOperation(value = "验证Token")
    @PostMapping(value = "/check", name = "验证Token")
    public Result check(HttpServletRequest httpServletRequest) {
        String session = httpServletRequest.getHeader("Set-Cookie");
        if (!StringUtils.isBlank(session)) {
            if (redisTemplate.hasKey(session)) {
                UserDetails userDetails = (UserDetails) redisTemplate.opsForValue().get(session);
                redisTemplate.opsForValue().set(session, userDetails, 30L, TimeUnit.DAYS);
                int count = newReportMapper.IsBlock(Long.parseLong(userDetails.getPhone()));
                if (count >0){
                    ExceptionUtils.error(UserCode.USER_IS_AUDIT);
                }
                userDetails.setUserData(userFeiController.queryUserData(userDetails.getId()));
                userDetails.setDays(getDays(userDetails.getVolunteerTime()));
                userDetails.setVolunteerUsers(userFeiController.queryUserVolunteer(userDetails.getId()));
//                userDetails.setId(null);
                userDetails.setOpenId(null);
                return Result.success(userDetails);
            }
            ExceptionUtils.error(CommonCode.TOKEN_ERROR);
        }
        return Result.error(CommonCode.AUTH_NOT_SUCCESS);
    }

    @ApiOperation(value = "获取授权")
    @PostMapping(value = "/getAuth", name = "获取授权")
    public Result auth(@RequestBody WxLogin wxLogin, HttpServletResponse httpServletResponse) {
        if (StringUtils.isBlank(wxLogin.getCode())) {
            ExceptionUtils.error(AuthCode.CODE_NOT);
        }
        //获取code与session_key
        WxInfo wxInfo = apiService.getSession(wxLogin.getCode());
        if (StringUtils.isBlank(wxInfo.getOpenid())) {
            ExceptionUtils.error(AuthCode.OPEN_ID_ERROR);
        }
        String openId = wxInfo.getOpenid();
        if (StringUtils.isBlank(wxLogin.getIv())) {
            return Result.success(CommonCode.AUTH_NOT_SUCCESS, wxInfo);
        }

        //获取手机号码
        UserInfo info = apiService.getDetails(wxLogin, wxInfo.getSession_key());
        //查询用户是否存在
        UserDetails userDetails = userFeiController.queryByOpenId(openId);
        //查询是否为封禁用户
        if (userDetails != null) {
            int count = newReportMapper.IsBlock(Long.parseLong(userDetails.getPhone()));
            if (count > 0) {
                return Result.error(UserCode.USER_IS_AUDIT);
            }
        }
        String sessionId = passwordEncode.encode(String.valueOf(idWorker.nextId()));
        if (userDetails != null) {
            //判断是否需要更新数据
            if (!StringUtils.equals(userDetails.getName(), wxLogin.getName())
                    || !StringUtils.equals(userDetails.getPicture(), wxLogin.getImage())
                    || (info.getPhone() != null && !StringUtils.equals(userDetails.getPhone(), info.getPhone()))) {
                // 如果info不空，说明获取到了手机号，将其替换
                if (info.getPhone() != null) {
                    userDetails.setPhone(info.getPhone());
                }
                PutUser putUser = new PutUser(wxLogin.getName(), userDetails.getPhone(), wxLogin.getImage());
                PutUserFei putUserFei = new PutUserFei();
                BeanUtils.copyProperties(putUser, putUserFei);
                putUserFei.setOpenId(userDetails.getOpenId());
                userFeiController.PutUser(putUserFei);
                userDetails.setName(wxLogin.getName());
                //userDetails.setPhone(userDetails.getPhone());
                userDetails.setPicture(wxLogin.getImage());
            }
            // 返回令牌与 用户数据 令牌存储用户所有信息 key 由 SessionId担任
            // 前面加上base64编码的userId
            String idBase64 = Base64Utils.encodeToString(userDetails.getId().toString());
            sessionId = idBase64 + sessionId;
            redisTemplate.opsForValue().set(sessionId, userDetails, 30L, TimeUnit.DAYS);
            httpServletResponse.setHeader("Set-Cookie", sessionId);
            userDetails.setVolunteerUsers(userFeiController.queryUserVolunteer(userDetails.getId()));
            userDetails.setOpenId(null);
            userDetails.setUserData(userFeiController.queryUserData(userDetails.getId()));
            return Result.success(userDetails);
        }
        // 注册时，若手机号码为null，则报错返回
        if (info.getPhone() == null) {
            ExceptionUtils.error(AuthCode.PHONE_ERROR);
        }
        info.setName(wxLogin.getName());
        info.setPicture(wxLogin.getImage());
        info.setOpenId(openId);
        userDetails = userFeiController.create(info);
        if (userDetails == null) {
            ExceptionUtils.error(FeiCode.FEI_ERROR);
        }
        // 返回令牌与 用户数据 令牌存储用户所有信息 key 由 SessionId担任
        // 前面加上base64编码的userId
        String idBase64 = Base64Utils.encodeToString(userDetails.getId().toString());
        sessionId = idBase64 + sessionId;
        redisTemplate.opsForValue().set(sessionId, userDetails, 30L, TimeUnit.DAYS);
        httpServletResponse.setHeader("Set-Cookie", sessionId);
        userDetails.setId(null);
        userDetails.setOpenId(null);
        userDetails.setVolunteerUsers(null);
        userDetails.setOpenId(null);
        return Result.success(userDetails);
    }


    @Data
    static class TestWxLogin {
        private String openId;

        private String name;

        private String image;
    }
    @ApiOperation(value = "开发测试获取授权")
    @PostMapping(value = "/devTestGetAuth", name = "开发测试获取授权")
    public Result devTestGetAuth(@RequestBody TestWxLogin wxLogin, HttpServletResponse httpServletResponse) {
        String openId = wxLogin.getOpenId();
        //获取手机号码
        UserInfo info = new UserInfo();
        info.setPhone("12345678901");
        //查询用户是否存在
        UserDetails userDetails = userFeiController.queryByOpenId(openId);
        String sessionId = passwordEncode.encode(String.valueOf(idWorker.nextId()));
        if (userDetails != null) {
            //判断是否需要更新数据
            if (!StringUtils.equals(userDetails.getName(), wxLogin.getName()) || !StringUtils.equals(userDetails.getPicture(), wxLogin.getImage())
                    || !StringUtils.equals(userDetails.getPhone(), info.getPhone())) {
                PutUser putUser = new PutUser(wxLogin.getName(), userDetails.getPhone(), wxLogin.getImage());
                PutUserFei putUserFei = new PutUserFei();
                BeanUtils.copyProperties(putUser, putUserFei);
                putUserFei.setOpenId(userDetails.getOpenId());
                userFeiController.PutUser(putUserFei);
                userDetails.setName(wxLogin.getName());
                userDetails.setPhone(userDetails.getPhone());
                userDetails.setPicture(wxLogin.getImage());
            }
            // 返回令牌与 用户数据 令牌存储用户所有信息 key 由 SessionId担任
            // 前面加上base64编码的userId
            String idBase64 = Base64Utils.encodeToString(userDetails.getId().toString());
            sessionId = idBase64 + sessionId;
            redisTemplate.opsForValue().set(sessionId, userDetails, 7L, TimeUnit.DAYS);
            httpServletResponse.setHeader("Set-Cookie", sessionId);
            userDetails.setVolunteerUsers(userFeiController.queryUserVolunteer(userDetails.getId()));
            userDetails.setOpenId(null);
            userDetails.setUserData(userFeiController.queryUserData(userDetails.getId()));
            return Result.success(userDetails);
        }
        info.setName(wxLogin.getName());
        info.setPicture(wxLogin.getImage());
        info.setOpenId(openId);
        userDetails = userFeiController.create(info);
        if (userDetails == null) {
            ExceptionUtils.error(FeiCode.FEI_ERROR);
        }
        // 返回令牌与 用户数据 令牌存储用户所有信息 key 由 SessionId担任
        // 前面加上base64编码的userId
        sessionId = Base64Utils.encodeToString(userDetails.getId().toString()) + sessionId;
        System.out.println(sessionId);
        redisTemplate.opsForValue().set(sessionId, userDetails, 7L, TimeUnit.DAYS);
        httpServletResponse.setHeader("Set-Cookie", sessionId);
        userDetails.setId(null);
        userDetails.setOpenId(null);
        userDetails.setVolunteerUsers(null);
        userDetails.setOpenId(null);
        return Result.success(userDetails);
    }
}
